home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part1 / 7785 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  7.7 KB

  1. Path: mail2news.demon.co.uk!genesis.demon.co.uk
  2. From: Lawrence Kirby <fred@genesis.demon.co.uk>
  3. Newsgroups: comp.lang.c
  4. Subject: Re: What is &Variable (declared as: char Variable[10])?
  5. Date: Wed, 28 Feb 96 20:32:50 GMT
  6. Organization: none
  7. Message-ID: <825539570snz@genesis.demon.co.uk>
  8. References: <4gqpa1$3h9@alcor.usc.edu> <4gsdno$1bg@umbc9.umbc.edu> <4gtab6$acb@ceylon.gte.com> <313318b8.53776146@nntp.ix.netcom.com> <4h1u9d$sqq@ceylon.gte.com>
  9. Reply-To: fred@genesis.demon.co.uk
  10. X-NNTP-Posting-Host: genesis.demon.co.uk
  11. X-Newsreader: Demon Internet Simple News v1.27
  12. X-Mail2News-Path: genesis.demon.co.uk
  13.  
  14. In article <4h1u9d$sqq@ceylon.gte.com> g051286 "Brenda" writes:
  15.  
  16. >What is the definition of a pointer?
  17.  
  18. A pointer is a *type*, more precisely a derived type (which classes it with
  19. arrays, structures, unions and functions and distinguishes it from integer
  20. and floating point types which are 'basic types').
  21.  
  22. > I have always been taught that a
  23. >pointer is simply an address in memory, and an array name (i.e. myarray)
  24. >is simply a CONSTANT address.  I don't think this statement is all that
  25. >radical.
  26.  
  27. It may not be radical but it is unfortunately wrong! :-)
  28.  
  29. Consider something simple like:
  30.  
  31. int i = 2;
  32.  
  33. This is a declaration of an integer variable i. In this case it is also
  34. a definition because it reserves space for an object (of type int). The object
  35. is initialised to the value 2. The identifier i is used to reference (or in
  36. standard terms `designate') the object and as such is termed an lvalue
  37. (which in C simply means something that designates an object). All objects
  38. (and also functions) have an address which is, if you like, a handle that can
  39. be used to refer to the object (as an alternative to an identifier). C
  40. pointers can hold addresses but they are more than that - they have an
  41. inherent type (which is visible to the program) and possibly other components
  42. such as bounds checking information (which is not visible to the program).
  43. Consider:
  44.  
  45. int *p = &i;
  46.  
  47. This defines a pointer variable (i.e. creates an object of type int * and
  48. declares an identifier p that designates it). &i evaluates to a pointer with
  49. type int * and value `address of object designated by i' and this is used to
  50. initialise p. So now we have:
  51.  
  52. 1. An int object which we can access through the identifier i. The identifier
  53.    is an lvalue so we can write, for example:
  54.  
  55.        i = <expr>;
  56.  
  57.    to change its value.
  58.  
  59. 2. A value 2 in that object. When we ask the compiler to take the value of an
  60.    expression that designates that object e.g.
  61.  
  62.        printf("%d\n", i)
  63.  
  64.    the result will be 2.
  65.  
  66. 3. An int * (i.e. pointer) object which we can access through the identifier
  67.    p e.g.
  68.  
  69.        p = NULL;
  70.  
  71. 4. A value `address of object designated by i' in that object. An address
  72.    isn't that useful unless we can reference what it points to, which is what
  73.    the * operator allows us to do. e.g.
  74.  
  75.    *p = <expr>;
  76.  
  77.    * takes the value of a pointer as its operand and produces as its result
  78.    an lvalue which designates what the operand pointed to. In the case above
  79.    p points to the object that i designates, so *p and i designate the same
  80.    object - they can be used interchangeably.
  81.  
  82. The examples above show that context makes a difference to how things are
  83. treated in C. For example in:
  84.  
  85.     i = i + 1;
  86.  
  87. i is in a context (the lhs of =) that requires an lvalue (in this case
  88. a modifiable lvalue) and in a context (an operand of +) that simply requires
  89. a value (call it an rvalue). How i is treated in these two contexts is
  90. clearly different. So now consider:
  91.  
  92.     int a[10] = { 0 };
  93.  
  94. which defines an array of 10 integers and initialises each of them to 0.
  95. What we have here is a compound object - the array as a whole may be
  96. viewed as an object but so may each of its individual elements. a itself
  97. is an identifier which designates the entire array i.e. the 10 int objects
  98. viewed as a single unit. It has type (int [10]) and is purely and simply an
  99. array. In particular there is nothing pointerish about it at all here.
  100.  
  101. It is considered that arrays are not 'first class' types in C - there is
  102. very little you can do to an array as a whole - you usually have to work
  103. on its elements. Some of the things you can do with arrays are:
  104.  
  105. 1. Declare/define and initialise them
  106.  
  107. 2. Take their address with &
  108.  
  109. 3. Take their size with sizeof.
  110.  
  111. The thing that C does not really support is the idea of an array 'value' (or
  112. more accurately a value with array type). For example you can't assign
  113. arrays (as you can even with structs), pass array typed arguments or in effect
  114. do anything to the contents of the array as a whole. However I can write:
  115.  
  116.    p = a;
  117.  
  118. So what is happening here? C has a rule that if I try to take the value of
  119. an array (i.e. I place an expression that designates an array in a context
  120. that requires an 'rvalue') the compiler will give me a pointer to the
  121. first element of the array so:
  122.  
  123.    p = a;
  124.  
  125. is equivalent to:
  126.  
  127.    p = &a[0];
  128.  
  129.  
  130. This doesn't mean that a is a pointer, only that it evaluates to a pointer
  131. in some (and certainly not all) circumstances. Just as with:
  132.  
  133.    const int j = 5;
  134.  
  135. j is not the value 5 but does evaluate to it in circumstances where
  136. evaluation is required. *p and *a are lvalues which both designate the int
  137. object that is the first element of a, just as previously *p and i were
  138. lvalues that designated the same object.
  139.  
  140. The oddity is that when evaluated an array lvalue does not generate a value
  141. (rvalue) that has array type.
  142.  
  143. > Of course there are differences between arrays and pointers
  144. >due to the fact that an array is a CONSTANT address and a pointer is a
  145. >VARIABLE address.
  146.  
  147. The reason that you can't simplify the above discussion down to saying
  148. that an array name is a pointer is that there are many contexts where it can
  149. appear where it does *not* evaluate to a pointer, e.g. declarations and as
  150. the operand of & or sizeof; basically any context that doesn't require
  151. an rvalue.
  152.  
  153. I said at the start that pointers and arrays are (derived) types. As far as
  154. the type system itself goes there is no relation at all between arrays and
  155. pointers. When you define a pointer you are not reserving space for
  156. any form of array and similarly if you define an array you are not reserving
  157. space for any form of pointer (other than any pointers that may form part of
  158. its elements e.g. char *ap[100] an array of pointers to char).
  159.  
  160. > And the reason I said you shouldn't (note shouldn't
  161. >not couldn't) say &myarray is:
  162.  
  163. In ANSI C you can take the address of an array which is useful for dealing
  164. with arrays of arrays (loosely called 2D arrays). Prior to ANSI C it was
  165. a problem area.
  166.  
  167. >(from "A Book On C", Kelley & Pohl, pg 200)
  168. >Constructs not to be pointed at:
  169. >1. Do not point at constants. (&3)
  170.  
  171. You can't do that because 3 is not an lvalue. You can however take the
  172. address of j defined above.
  173.  
  174. >2. Do not point at arrays; an array name is a constant. (int a[77]; &a)
  175.  
  176. This is legal in ANSI C. The fact that it is in any sense constant is not
  177. relevant. The sense in which is constant is the same as the sense in which
  178. &i is constant - objects keep the same address for the duration of their
  179. lifetime (apart from possibly heap objects due to the unfortunate way in
  180. which realloc() is defined in the standard).
  181.  
  182. >3. Do not point at ordinary expressions &(k + 99)
  183.  
  184. + does not produce a result that is an lvalue.
  185.  
  186. >4. Do not point at register variables. (register v; &v)
  187.  
  188. That is really all register has come to mean - it is illegal to take its
  189. address.
  190.  
  191. >So again I say, myarray is DEFINITELY a pointer (i.e. address in memory).
  192.  
  193. That is only true in the one specific case where you are talking about the
  194. value of myarray in an rvalue context. It is not a generality.
  195.  
  196. -- 
  197. -----------------------------------------
  198. Lawrence Kirby | fred@genesis.demon.co.uk
  199. Wilts, England | 70734.126@compuserve.com
  200. -----------------------------------------
  201.